package tuding.android.bigplanettracks.tracks.writer;

//import java.io.BufferedReader;
import java.io.File;
//import java.io.InputStreamReader;
import java.net.SocketException;
import java.net.SocketTimeoutException;
//import java.net.SocketTimeoutException;
//import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import tuding.android.bigplanettracks.BigPlanet;
import tuding.android.bigplanettracks.maps.MarkerManager;
import tuding.android.bigplanettracks.maps.storage.SQLLocalStorage;
import tuding.android.bigplanettracks.maps.tuding.ActionBase;
import tuding.android.bigplanettracks.maps.tuding.ActionNotes;
import tuding.android.bigplanettracks.maps.tuding.LocationEx;
import tuding.android.bigplanettracks.tracks.TrackTabViewActivity;
import tuding.android.bigplanettracks.tracks.db.TrackDBAdapter;
import tuding.android.bigplanettracks.tudingConnection.BaseConnection;
import tuding.android.bigplanettracks.util.Preferences;

import android.database.Cursor;
import android.os.Handler;
import android.os.Message;
import android.util.Log;


/**
 * @author Y.Pan
 */
public class GpxTrackWriterEx {
	private ArrayList<LocationEx> locationListEx = null;
	private GpxFileEx gpxFileEx = null;
	private long trackID=0;
	//private int photonum = 0;
	private Handler trackListViewHandler=null;
	public static final int EXPORT_SUCCESS=1;
	public static final int EXPORT_FAIL=0; 
	public static final int UPLOAD_SUCCESS=3;
	public static final int UPLOAD_FAIL_UNKNOWN_ERROR=2;
	public static final int UPLOAD_FAIL_DUE_TO_TIMESTAMP_ERROR=4;
	public static final int UPLOAD_CONNECT_TIMEOUT = 5;
	public static final int UPLOAD_DATA_TIMEOUT = 6;
	public static final int ILLEGAL_TRACKID = 7;
	public static final int LOGIN_FAIL = 8;
	public static final int NEEDLOGIN = 9;
	public static final int EXCEPTION_UNKNOWN = 10;
	public static final int UPLOAD_FAIL_CONNECTION_ERROR = 11;
	public static final int SOCKETEXCEPTION = 12;
	
	private static final String UPLOAD_SUCCESS_TEXT = "GpxSuccess";
	private static final String UPLOAD_TIMESTAMP_ERROR_TEXT = "GpxTimeStampError";
	private boolean toTuding = false;
	
	class myThread extends Thread {
		
		public void run() {
			
			Message m = null;
			if (trackID > 0) {

				try{
					//Retrive the track's attributes from Sqlite
					Cursor myCursor = BigPlanet.DBAdapter.getTrack(trackID); // SQLExcetpion
					String trackName = myCursor.getString(myCursor.getColumnIndexOrThrow(TrackDBAdapter.FIELD_name)); // IllegalArgumentException
					String trackDescription = myCursor.getString(myCursor.getColumnIndexOrThrow(TrackDBAdapter.FIELD_description));
				
					myCursor.close();
					if (trackName.equals(""))
						trackName = "New_uploaded_track_from_android";
					
					locationListEx = new ArrayList<LocationEx>();
					myCursor = BigPlanet.DBAdapter.getTrackPoints(trackID);
					for (int i=0; i < myCursor.getCount(); i++) {
						double latitude = myCursor.getDouble(myCursor.getColumnIndexOrThrow(TrackDBAdapter.FIELD_latitude));
						double longitude = myCursor.getDouble(myCursor.getColumnIndexOrThrow(TrackDBAdapter.FIELD_longitude)); 
						String strGMTTime = myCursor.getString(myCursor.getColumnIndexOrThrow(TrackDBAdapter.FIELD_time));
						double altitude = myCursor.getDouble(myCursor.getColumnIndexOrThrow(TrackDBAdapter.FIELD_altitude));
						float speed = myCursor.getFloat(myCursor.getColumnIndexOrThrow(TrackDBAdapter.FIELD_speed));
						int actionType = myCursor.getInt(myCursor.getColumnIndexOrThrow(TrackDBAdapter.FIELD_actionType));
						long actionID = myCursor.getLong(myCursor.getColumnIndexOrThrow(TrackDBAdapter.FIELD_actionID));
						
						LocationEx locationEx = new LocationEx("");
						locationEx.setLatitude(latitude);
						locationEx.setLongitude(longitude);
						locationEx.setAltitude(altitude);
						locationEx.setSpeed(speed);
						locationEx.setActionType(actionType);
						locationEx.setActionID(actionID);
						TrackDBAdapter.setGMTTimeString(locationEx, strGMTTime);
						locationListEx.add(locationEx);
						myCursor.moveToNext();
					}
					myCursor.close();
					
					// Need to check the capacity of the SD card before generating the GPX file
					Log.i("Message", "Generate GPX File...");
					Map<String, File> files = new HashMap<String, File>();
					
					gpxFileEx = new GpxFileEx(trackName, trackDescription);
					ActionNotes actionN = new ActionNotes();
					for (LocationEx locationEx: locationListEx) {
						if(locationEx.getActionType() == MarkerManager.ACTION_TYPE_NOTES) {
							ActionBase actionB = actionN.getActionNotesByID(locationEx.getActionID());
							String desc = ""+(actionB.getName()==null?"":actionB.getName())+(actionB.getDescription()==null?"":actionB.getDescription());
							gpxFileEx.saveLocation(locationEx, MarkerManager.ACTION_TYPE_NOTES, desc, "");
						} else if(locationEx.getActionType() == MarkerManager.ACTION_TYPE_PHOTO) {
							ActionBase actionB = actionN.getActionPhotoByID(locationEx.getActionID());
							String desc = ""+(actionB.getName()==null?"":actionB.getName())+(actionB.getDescription()==null?"":actionB.getDescription());
							gpxFileEx.saveLocation(locationEx, MarkerManager.ACTION_TYPE_PHOTO, desc, actionB.getUri());
							files.put(actionB.getUri(), new File(SQLLocalStorage.TRACK_PATH+"photo/"+actionB.getUri()));
						} else {
							gpxFileEx.saveLocation(locationEx);
						}
					}
					actionN.close();
					gpxFileEx.closeFile();
					Log.i("Message", "Finish...the GPX file exists in the directory: "+SQLLocalStorage.TRACK_PATH+"export/");
					
					// Added by Panyf
					if (toTuding) {
						Map<String, String> params = new HashMap<String, String>();
						params.put("do", "loadgpx");
						params.put("username", Preferences.getUsername());
						params.put("password", Preferences.getPassword());
						
						params.put("tname", trackName);
						params.put("tdesc", trackDescription);
						int tmp = Preferences.getTudingUploadPrivacy();
						if(tmp == 2) tmp = 3;
						params.put("priv", ""+tmp);
						
						files.put("gpxfile", gpxFileEx.getFileHandler());
						
						String postUrl = BigPlanet.SERVER_ADDRESS+"android_upload.php";
						
						// Post to tuding
						String rc = BaseConnection.postToTuding(postUrl, params, files);

						
						// Show the return value for debug:
						Log.d("UPLOAD", "rc: "+rc);
						
						
						if (rc.contains(UPLOAD_TIMESTAMP_ERROR_TEXT)) {
                            Log.i("Message", "Failed to upload gpx file to Tuding due to timestamp error");
                            BigPlanet.DBAdapter.markTrackLoaded(trackID, true);
							//sent message back to TrackListViewAvtivity handler
							String obj = "Fail!";
							m = trackListViewHandler.obtainMessage(UPLOAD_FAIL_DUE_TO_TIMESTAMP_ERROR, 0, 1, obj.toString());
							if(trackListViewHandler != null)
								trackListViewHandler.sendMessage(m);
							else
								throw new Error("trackListViewHandler is Null");
							
						} else if(rc.contains(UPLOAD_SUCCESS_TEXT)) {
							String obj = "Success!";
							m = trackListViewHandler.obtainMessage(UPLOAD_SUCCESS, 1, 1, obj);
							BigPlanet.DBAdapter.markTrackLoaded(trackID, true);
							
							if (trackListViewHandler != null)
								trackListViewHandler.sendMessage(m);
							else
								throw new Error("trackListViewHandler is Null");
							
						} else if(rc.contains("PasswordInvalid") || rc.contains("NoUserNameProvided")) {
							Log.i("Message", "Failed to upload gpx file to Tuding");
							String obj = "Login Failed!";
							m = trackListViewHandler.obtainMessage(LOGIN_FAIL, 0, 1, obj.toString());
							if(trackListViewHandler != null)
								trackListViewHandler.sendMessage(m);
							else
								throw new Error("trackListViewHandler is Null");

						} else {
							Log.i("Message", "Failed to upload gpx file to Tuding");
							//sent message back to TrackListViewAvtivity handler
							String obj = "Failed with rc: "+rc;
							m = trackListViewHandler.obtainMessage(UPLOAD_FAIL_CONNECTION_ERROR, 0, 1, obj.toString());
							if(trackListViewHandler != null)
								trackListViewHandler.sendMessage(m);
							else
								throw new Error("trackListViewHandler is Null");
							
						}
						
					} else { // no need to upload to tuding
						String obj = "Success!";
						m = trackListViewHandler.obtainMessage(EXPORT_SUCCESS, 1, 1, obj);

						if (trackListViewHandler != null)
							trackListViewHandler.sendMessage(m);
						else
							throw new Error("trackListViewHandler is Null");
					}
				} catch(SocketException e) {
					String obj = "Socket!";
					m = trackListViewHandler.obtainMessage(SOCKETEXCEPTION, 0, 1, obj.toString());
					if(trackListViewHandler != null)
						trackListViewHandler.sendMessage(m);
					else
						throw new Error("trackListViewHandler is Null");
					Log.d("UPLOAD", "Exception happened with message: "+e.getMessage());
					e.printStackTrace();
				} catch(SocketTimeoutException  e) {
					// Connection exception
					String obj = "Timeout!";
					m = trackListViewHandler.obtainMessage(UPLOAD_CONNECT_TIMEOUT, 0, 1, obj.toString());
					if(trackListViewHandler != null)
						trackListViewHandler.sendMessage(m);
					else
						throw new Error("trackListViewHandler is Null");
					Log.d("UPLOAD", "Exception happened with message: "+e.getMessage());
					e.printStackTrace();
					
				} catch(Exception e) {
					String obj = "Fail!";
					m = trackListViewHandler.obtainMessage(EXCEPTION_UNKNOWN, 0, 1, obj.toString());
					if(trackListViewHandler != null)
						trackListViewHandler.sendMessage(m);
					else
						throw new Error("trackListViewHandler is Null");
					Log.d("UPLOAD", "Exception happened with message: "+e.getMessage());
					e.printStackTrace();
					
				} finally {
					try {
					    TrackTabViewActivity.myTrackExportDialog.dismiss();
					} catch(Exception e) {}
				}
			} else {
				//sent message back to TrackListViewAvtivity handler
				try {
				    TrackTabViewActivity.myTrackExportDialog.dismiss();
			    } catch(Exception e) {}
				String obj = "Fail!";
					m = trackListViewHandler.obtainMessage(ILLEGAL_TRACKID, 0, 1, obj.toString());
					if(trackListViewHandler != null)
						trackListViewHandler.sendMessage(m);
					else
						throw new Error("trackListViewHandler is Null");
				Log.e("GpxTrackWriter", "myTrackDBAdapter == null or trackID <= 0");
			} 
		}// end of run
	}
	
	public void setHandler(Handler handler) {
		this.trackListViewHandler = handler;
	}
	
	public void setTrackID(long trackID) {
		this.trackID = trackID;
	}
	
	public void setUpLoadtoTuding() {
	    this.toTuding = true;
	}
	
	public void saveToFile() {
//		Log.i("Message", "Start GpxFile Export Thread");
		myThread exportThread = new myThread();
		exportThread.setName("Upload Thread");
		exportThread.start();
	}
}
